var express = require('express')
var router = express.Router()
var fs = require('fs')
const path = require('path')
let url = require('url')
let http = require('http')
var multiparty = require('multiparty')
require('shelljs/global')
const parseApk = require('../utils/appt')
const { diffFromApk } = require('../utils/bundle')
var realm = require('../models')
var { AutoIncVersionId } = require('../models/version')
var { AutoIncAppId } = require('../models/app')

function dateFormat(date, fmt) {
  if (null == date || undefined == date) return ''
  var o = {
    'M+': date.getMonth() + 1, //月份
    'd+': date.getDate(), //日
    'h+': date.getHours(), //小时
    'm+': date.getMinutes(), //分
    's+': date.getSeconds(), //秒
    S: date.getMilliseconds() //毫秒
  }
  if (/(y+)/.test(fmt))
    fmt = fmt.replace(
      RegExp.$1,
      (date.getFullYear() + '').substr(4 - RegExp.$1.length)
    )
  for (var k in o)
    if (new RegExp('(' + k + ')').test(fmt))
      fmt = fmt.replace(
        RegExp.$1,
        RegExp.$1.length == 1 ? o[k] : ('00' + o[k]).substr(('' + o[k]).length)
      )
  return fmt
}

Date.prototype.toJSON = function() {
  return dateFormat(this, 'yyyy-MM-dd hh:mm:ss')
}

/**
 * 获取应用列表
 */
router.get('/apps', async function(req, res, next) {
  const data = await new Promise((resolve, reject) => {
    const data = []
    const apps = realm.objects('App')
    data.push(...apps)
    resolve(data)
  })
  res.send({
    data,
    result: 'success',
    msg: ''
  })
})

/**
 * 查询应用信息
 */
router.get('/apps/:id', async (req, res) => {
  const data = await new Promise((resolve, reject) => {
    resolve(
      realm.objects('App').filtered('id = $0', parseInt(req.params.id))[0]
    )
  })
  res.send({
    data,
    result: data ? 'success' : 'error',
    msg: data ? '' : '查询失败'
  })
})

/**
 * 删除应用
 */
router.delete('/apps/:id', async (req, res) => {
  const data = await new Promise((resolve, reject) => {
    if (
      realm.objects('Version').filtered('appId = $0', req.params.id).length ===
      0
    ) {
      realm.write(() => {
        realm.delete(
          realm.objects('App').filtered('id = $0', parseInt(req.params.id))
        )
        resolve(true)
      })
    } else {
      resolve(false)
    }
  })
  res.send({
    data,
    result: data ? 'success' : 'error',
    msg: data ? '' : '删除失败'
  })
})

/**
 * 新增应用
 */
router.post('/apps/add', async (req, res) => {
  try {
    await new Promise((resolve, reject) => {
      realm.write(() => {
        let id = AutoIncAppId()
        realm.create('App', { ...req.body, id, appId: id }, true)
        resolve()
      })
    })
    res.send({
      result: 'success',
      msg: ''
    })
  } catch (error) {
    res.send({
      result: 'success',
      msg: error.message
    })
  }
})

/**
 * 修改应用信息
 */
router.post('/apps/:id', async (req, res) => {
  try {
    await new Promise((resolve, reject) => {
      realm.write(() => {
        let id = parseInt(req.params.id)
        realm.create('App', { ...req.body, id, appId: id }, true)
        resolve()
      })
    })
    res.send({
      result: 'success',
      msg: ''
    })
  } catch (error) {
    res.send({
      result: 'success',
      msg: error.message
    })
  }
})

/**
 * 检查版本更新接口
 */
router.post('/q', async (req, res, next) => {
  try {
    if (!req.body.appId || !req.body.versionCode) {
      throw new Error('appId或versionCode不能为空')
    }
    const data = await new Promise((resolve, reject) => {
      let data = []
      let versions = realm
        .objects('Version')
        .filtered('enable = true AND appId = $0', req.body.appId)
      versions = versions.filtered(
        'targetVersion.@count == 0 OR targetVersion.value = $0',
        parseInt(req.body.versionCode)
      )
      apkVersion = versions
        .filtered(
          `versionType = "apk" AND versionCode > ${req.body.versionCode}`
        )
        .sorted('id', true)
      resVersion = versions.filtered('versionType = "res"').sorted('id', true)
      patchVersion = versions
        .filtered('versionType = "patch"')
        .sorted('id', true)
      if (apkVersion.length > 0) {
        data.push(apkVersion[0])
      }
      if (resVersion.length > 0) {
        data.push(resVersion[0])
      }
      if (patchVersion.length > 0) {
        data.push(patchVersion[0])
      }
      resolve(data)
    })
    res.send({
      result: 'success',
      msg: '查询成功',
      data
    })
  } catch (error) {
    res.send({
      result: 'error',
      msg: error.message,
      data: []
    })
  }
})

router.get('/versions', async (req, res, next) => {
  let total = 0
  const data = await new Promise((resolve, reject) => {
    let versions = realm.objects('Version').sorted('id', true)
    if (req.query.appId) {
      versions = versions.filtered(`appId = "${req.query.appId}"`)
    }
    if (req.query.type) {
      versions = versions.filtered(`versionType = "${req.query.type}"`)
    }
    if (req.query.maxVersionCode) {
      versions = versions.filtered(`versionCode < ${req.query.maxVersionCode}`)
    }
    let pageIndex = 0,
      pageSize = 20
    if (req.query.pageIndex && !isNaN(req.query.pageIndex)) {
      pageIndex = req.query.pageIndex
    }
    if (req.query.pageSize && !isNaN(req.query.pageSize)) {
      pageSize = req.query.pageSize
    }
    total = versions.length
    resolve(versions.slice(pageIndex * pageSize, (1 + pageIndex) * pageSize))
  })
  res.send({
    data,
    result: 'success',
    msg: '',
    total
  })
})

/**
 * 添加版本
 */
router.post('/versions/add', function(req, res, next) {
  var form = new multiparty.Form()
  fs.exists('../uploads/', exist => {
    if (!exist) {
      fs.mkdir('../uploads/', err => {
        if (err) {
          console.log(err)
        }
      })
    }
  })
  fs.exists(path.resolve(process.env.absolutePath, 'upload'), exist => {
    if (!exist) {
      fs.mkdir(path.resolve(process.env.absolutePath, 'upload'), err => {
        if (err) {
          console.log(err)
        }
      })
    }
  })
  form.uploadDir = '../uploads/'
  form.maxFilesSize = 200 * 1024 * 1024
  form.parse(req, async function(err, fields, files) {
    try {
      if (err || !fields.appId || !fields.appName) {
        res.send({
          result: 'error',
          msg: err.message || '参数错误',
          data: ''
        })
      } else {
        let url = ''
        if (files.file && files.file.length > 0) {
          const apkInfo = await new Promise((resolve, reject) => {
            parseApk(files.file[0].path, function(err, data) {})
              .then(resolve)
              .catch(console.log)
          })
          if (apkInfo) {
            var key = Number(new Date())
            fs.copyFileSync(
              files.file[0].path,
              path.resolve(process.env.absolutePath, `upload/${key}.apk`)
            )
            url = `${process.env.uploadPrefix}upload/${key}.apk`
            console.log(apkInfo)
            realm.write(() => {
              realm.create(
                'Version',
                {
                  id: AutoIncVersionId(),
                  ...apkInfo,
                  versionCode: parseInt(apkInfo.versionCode),
                  createTime: new Date(),
                  targetVersion: [],
                  url,
                  versionType: 'apk',
                  enable: true,
                  appId: fields.appId[0],
                  appName: fields.appName[0]
                },
                true
              )
            })
            res.send({
              result: 'success',
              msg: '发布成功',
              data: ''
            })
          } else {
            res.send({
              result: 'error',
              msg: '应用解析失败',
              data: ''
            })
          }
          fs.unlinkSync(files.file[0].path)
        } else {
          url = fields.fileUrl[0]
          const file = await getFile(url)
          const apkInfo = await new Promise((resolve, reject) => {
            parseApk(file.path, function(err, data) {})
              .then(resolve)
              .catch(console.log)
          })
          if (apkInfo) {
            console.log(apkInfo)
            realm.write(() => {
              realm.create(
                'Version',
                {
                  id: AutoIncVersionId(),
                  ...apkInfo,
                  versionCode: parseInt(apkInfo.versionCode),
                  createTime: new Date(),
                  targetVersion: [],
                  url,
                  versionType: 'apk',
                  enable: true,
                  appId: fields.appId[0],
                  appName: fields.appName[0]
                },
                true
              )
            })
            res.send({
              result: 'success',
              msg: '发布成功',
              data: ''
            })
          } else {
            res.send({
              result: 'error',
              msg: '应用解析失败',
              data: ''
            })
          }
          fs.unlinkSync(file.path)
        }
      }
    } catch (error) {
      res.send({
        result: 'error',
        msg: error.message,
        data: ''
      })
    }
  })
})

/**
 * 对版本生成react-native差分包
 */
router.post('/versions/diffrn', async (req, res) => {
  const appId = req.body.appId
  const appName = req.body.appName
  const versionCode = req.body.versionCode
  const targetVersion = req.body.targetVersion
  if (!appId || !versionCode || !targetVersion) {
    res.send({
      data: '',
      msg: '必传参数不能为空',
      result: 'error'
    })
    return
  }
  fs.exists(path.resolve(process.env.absolutePath, 'upload'), exist => {
    if (!exist) {
      fs.mkdir(path.resolve(process.env.absolutePath, 'upload'), err => {
        if (err) {
          console.log(err)
        }
      })
    }
  })
  const data = ''
  const error = []
  try {
    const versions = realm.objects('Version').filtered('appId = $0', appId)
    const destVersion = versions.filtered(
      'versionCode = $0 AND versionType = "apk"',
      versionCode
    )
    let destFile
    if (destVersion.length > 0) {
      destFile = await getFile(destVersion[0].url)
    } else {
      throw new Error('目标版本不存在:' + versionCode)
    }
    let targetVersions = targetVersion.split(',')
    for (var i = 0; i < targetVersions.length; i++) {
      let d = targetVersions[i]
      let originVerison = versions.filtered(
        'versionCode = $0 AND versionType = "apk"',
        parseInt(d)
      )
      let srcFile, patchPath
      if (originVerison.length > 0) {
        if (
          realm
            .objects('Version')
            .filtered('enable = true AND appId = $0', appId)
            .filtered('versionType = "res"')
            .filtered('targetVersion.value = $0', parseInt(d)).length > 0
        ) {
          continue
        }
        srcFile = await getFile(originVerison[0].url)
        patchName = `upload/${md5(`${d}-${versionCode}-rn`)}.patch`
        patchPath = path.resolve(process.env.absolutePath, patchName)
        diffFromApk(srcFile.path, destFile.path, patchPath)
        let patchUrl = `${process.env.uploadPrefix}${patchName}`
        realm.write(() => {
          realm.create(
            'Version',
            {
              id: AutoIncVersionId(),
              targetVersion: [{ value: parseInt(d) }],
              createTime: new Date(),
              versionType: 'res',
              versionCode,
              enable: true,
              appId,
              appName,
              url: patchUrl,
              versionName: `${originVerison[0].versionName}->${destVersion[0].versionName}`,
              desc: `${d}->${versionCode}`
            },
            true
          )
        })
        fs.unlinkSync(srcFile.path)
      } else {
        throw new Error('源版本不存在:' + d)
      }
    }
  } catch (error) {
    console.log(error)
    error.push(error)
  }
  res.send({
    data,
    msg: error.length > 0 ? error[0].message : '',
    result: error.length == 0 ? 'success' : 'error'
  })
})

router.delete('/versions/:id', async (req, res) => {
  try {
    let versions = realm
      .objects('Version')
      .filtered('id = $0', parseInt(req.params.id))
    if (versions.length > 0) {
      realm.write(() => {
        realm.delete(versions)
      })
      res.send({
        data: '',
        result: 'success',
        msg: ''
      })
    } else {
      throw new Error('版本不存在')
    }
  } catch (error) {
    res.send({
      data: '',
      result: 'error',
      msg: error.message
    })
  }
})

/**
 * 修改版本信息
 */
router.post('/versions/:id', async (req, res) => {
  try {
    let versions = realm
      .objects('Version')
      .filtered('id = $0', parseInt(req.params.id))
    if (versions.length > 0) {
      realm.write(() => {
        Object.assign(versions[0], req.body)
      })
      res.send({
        data: '',
        result: 'success',
        msg: ''
      })
    } else {
      throw new Error('版本不存在')
    }
  } catch (error) {
    res.send({
      data: '',
      result: 'error',
      msg: error.message
    })
  }
})

/**
 * 查询版本详情
 */
router.get('/versions/:id', async (req, res) => {
  try {
    let versions = realm
      .objects('Version')
      .filtered('id = $0', parseInt(req.params.id))
    if (versions.length > 0) {
      const data = {}
      const updates = []
      data.versionInfo = versions[0]
      let appId = versions[0].appId
      let versionCode = versions[0].versionCode
      const promises = []
      data.updates = updates
      if (data.versionInfo.versionType === 'apk') {
        promises.push(
          new Promise(async (resolve, reject) => {
            let rn_update = realm
              .objects('Version')
              .filtered(
                'enable = true AND versionCode = $0 AND appId = $1 AND versionType = "res"',
                versionCode,
                appId
              )
            if (rn_update.length > 0) {
              updates.push(...rn_update)
            }
            resolve()
          })
        )
      }
      if (data.versionInfo.targetVersion.length > 0) {
        for (var i = 0; i < data.versionInfo.targetVersion.length; i++) {
          let versionCode = data.versionInfo.targetVersion[i].value
          promises.push(
            new Promise((resolve, reject) => {
              let update = realm
                .objects('Version')
                .filtered(
                  'versionCode = $0 AND appId = $1 AND versionType = "apk"',
                  versionCode,
                  appId
                )
              if (update.length > 0) {
                updates.push(update[0])
              }
              resolve()
            })
          )
        }
      }
      await Promise.all(promises)
      res.send({
        data,
        result: 'success',
        msg: ''
      })
    } else {
      throw new Error('版本不存在')
    }
  } catch (error) {
    res.send({
      data: '',
      result: 'error',
      msg: error.message
    })
  }
})

var crypto = require('crypto')
var fs = require('fs')

/**
 * 计算文件md5
 * @param {} file1
 */
const getFileMd5 = file1 => {
  return new Promise((reslove, reject) => {
    var rs = fs.createReadStream(file1)

    var hash = crypto.createHash('md5')
    rs.on('data', hash.update.bind(hash))

    rs.on('end', function() {
      reslove(hash.digest('hex'))
    })
  })
}

function md5(str) {
  return crypto
    .createHash('md5')
    .update(str)
    .digest('hex')
}

const getFile = filePath => {
  return new Promise((resolve, reject) => {
    fs.exists('../uploads/', exist => {
      if (!exist) {
        fs.mkdir('../uploads/', err => {
          if (err) {
            console.log(err)
          }
        })
      }
    })
    let file_name = url
      .parse(filePath)
      .pathname.split('/')
      .pop()
    let file = fs.createWriteStream('../uploads/' + file_name)
    http
      .get(filePath, function(res) {
        res.on('data', function(data) {
          file.write(data)
        })
        res.on('end', function() {
          file.end()
          resolve(file)
        })
      })
      .on('error', e => {
        reject(e)
      })
  })
}

const getStrMd5 = str => {
  var md5 = crypto.createHash('md5')
  md5.update(str)
  return md5.digest('hex')
}

router.post('/user/logout', (req, res, next) => {
  res.cookie('authority', 'guest')
  req.session.user = undefined
  res.send({
    status: 'ok',
    currentAuthority: 'guest'
  })
})

/**
 * 后台登录
 */
router.post('/user/login', function(req, res, next) {
  try {
    if (!req.body.userName || !req.body.password) {
      throw new Error('用户名或账号不能为空')
    }
    if (req.body.userName === 'admin' && req.body.password === 'Qq123456') {
      req.session.user = { name: 'admin' }
      res.cookie('authority', 'user')
      res.send({
        status: 'ok',
        currentAuthority: 'user'
      })
      return
    }
    throw new Error('用户名或账号错误')
  } catch (error) {
    res.cookie('authority', 'guest')
    res.send({
      msg: error.message,
      status: 'error',
      currentAuthority: 'guest'
    })
  }
})

/**
 * 当前登录用户
 */
router.get('/currentUser', function(req, res, next) {
  if (req.session.user) {
    res.send({
      name: req.session.user.name,
      avatar:
        'https://gw.alipayobjects.com/zos/rmsportal/BiazfanxmamNRoxxVxka.png'
    })
  } else {
    res.send({
      currentAuthority: 'guest',
      name: '未登录',
      userid: '00000001',
      avatar:
        'https://gw.alipayobjects.com/zos/rmsportal/BiazfanxmamNRoxxVxka.png'
    })
  }
})

module.exports = router
